/*
 * @(#)AabstractAlarmEsImpl.java   1.0  2022年3月15日
 * 
 * Copyright (c)	2014-2020. All Rights Reserved.	GuangZhou hhmk Technology Company LTD.
 */
package com.swift.monitor.core.alarm;

import java.io.IOException;
import java.util.Map;

import javax.annotation.PostConstruct;

import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.swift.dao.es.factory.ServiceIndexNameFactory;
import com.swift.monitor.core.config.MonitorConfig;
import com.swift.monitor.core.point.Point;
import com.swift.util.math.RandomUtil;
import com.swift.util.type.JsonUtil;
import com.swift.util.type.TypeUtil;
import com.swift.util.type.UrlUtil;

/**
 * 添加说明
 * 
 * @author zhengjiajin
 * @version 1.0 2022年3月15日
 */
public abstract class AabstractAlarmEsImpl<T extends Point> implements AlarmNotice<T> {

    protected static final Logger log = LoggerFactory.getLogger(AabstractAlarmEsImpl.class);

    private static RestHighLevelClient esClient;

    public abstract String getESTable();
    
    public abstract XContentBuilder getESMapping();

    // 是否已经存在表索引
    private boolean hasIndex = false;

    /**
     * @see com.swift.monitor.core.alarm.AlarmNotice#alarm(com.swift.monitor.core.point.Point)
     */
    @Override
    public void alarm(T t) {
        RestHighLevelClient es = getEsClient();
        if (es == null) return;
        createIndex();
        try {
            IndexRequest indexRequest = new IndexRequest(index(), "_doc", RandomUtil.createReqId());
            indexRequest.source(JsonUtil.toJson(t), XContentType.JSON);
            IndexResponse indexResponse = es.index(indexRequest, ServiceIndexNameFactory.COMMON_OPTIONS);
            if (indexResponse == null || indexResponse.getVersion() <= 0) {
                log.error("插入ES失败", indexResponse);
            }
        } catch (IOException e) {
            log.error("更新ES失败", e);
        }
    }

    private String index() {
        return (getIndexDev() + getESTable()).toLowerCase();
    }

    @PostConstruct
    private void createIndex() {
        if (hasIndex) return;
        String index = index();
        // 创建索引
        RestHighLevelClient es = getEsClient();
        if (es == null) return;
        try {
            GetIndexRequest request = new GetIndexRequest(index);
            boolean esIndex = es.indices().exists(request, RequestOptions.DEFAULT);
            if (esIndex) {
                hasIndex = true;
                return;
            }
            CreateIndexRequest createIndexRequest = new CreateIndexRequest(index());
            XContentBuilder mapping = getESMapping();
            if(mapping!=null) createIndexRequest.mapping(mapping);
            es.indices().create(createIndexRequest, RequestOptions.DEFAULT);
            hasIndex = true;
        } catch (Exception e) {
            log.error("创建ES索引失败", e);
            hasIndex = false;
        }
    }

    // http://es-***.elasticsearch.aliyuncs.com:9200?username=xxx&password=xxx&index_dev=test_
    public RestHighLevelClient getEsClient() {
        if (esClient != null) return esClient;
        if (TypeUtil.isNull(MonitorConfig.alarmESUrl)) return null;
        ServiceIndexNameFactory factory = new ServiceIndexNameFactory();
        factory.setUrl(MonitorConfig.alarmESUrl);
        factory.init();
        esClient = factory.getClient();
        return esClient;
    }

    public String getIndexDev() {
        if (TypeUtil.isNull(MonitorConfig.alarmESUrl)) return "";
        Map<String, String> map = UrlUtil.URLRequest(MonitorConfig.alarmESUrl);
        if (TypeUtil.isNull(map)) return "";
        String dev = map.get("index_dev");
        if (TypeUtil.isNull(dev)) return "";
        return dev;
    }
}
